package ch.tiktak.games.powersudoku;

import java.util.ArrayList;
import java.util.List;

/**
 * A grid with a fixed number of rows and columns.
 * Minimal Index is 1. not zero!
 */
abstract public class GenericGrid {

    /**
     * Data of the grid. first number is row index, second is column index
     */
    private List<int[]> data;

    private int rowsCount;
    private int columnsCount;

    public GenericGrid(int numberOfRows, int numberOfColumns) {
        this.rowsCount = numberOfRows;
        this.columnsCount = numberOfColumns;
        this.data = new ArrayList<int[]>();
    }

    public GenericGrid(List<int[]> data) {
        this.data = data;
        this.rowsCount = data.size();
        // Find line with most columns
        int cols = 0;
        for (int[] line : data) {
            cols = line.length > cols ? line.length : cols;
        }
        this.columnsCount = cols;
    }

    public GenericGrid (GenericGrid anotherGrid) {
        this(anotherGrid.getData());
    }

    public void insertLine(int... newElements) {
        data.add(newElements);
    }

    public int getValue(int rowIndex, int columnIndex) {
        return data.get(rowIndex - 1)[columnIndex - 1];
    }

    public void setValue(int rowIndex, int columnIndex, int dataToInsert) throws InvalidIndexException, InvalidSudokuValueException {
        if (!isValidColumnIndex(columnIndex)) {
            throw new InvalidIndexException("column", columnIndex, getColumnsCount());
        } else if (!isValidRowIndex(rowIndex)) {
            throw new InvalidIndexException("row", rowIndex, getRowsCount());
        } else {
            int[] rowContent = this.data.get(rowIndex - 1);
            rowContent[columnIndex - 1] = dataToInsert;
            this.data.set(rowIndex - 1, rowContent);
        }
    }

    public int getColumnsCount() {
        return columnsCount;
    }

    public int getRowsCount() {
        return rowsCount;
    }

    public List<int[]> getData() {
        return data;
    }

    public void setData(List<int[]> data) {
        this.data = data;
    }

    protected boolean isValidColumnIndex(int index) {
        return !(index < 1 || index > getColumnsCount());
    }

    protected boolean isValidRowIndex(int index) {
        return !(index < 1 || index > getRowsCount());
    }
}